import keyword
import math

print("Runoob")
# 打印所有python关键字
print(keyword.kwlist)
'''
多行注释
'''
# 单行注释

if True:
    print("true")
else:
    print("false")

# 多行语句 用 \ 换行
sencence= "hello ,my name is "\
"kim , I am from "\
    "ShaoXin City, I like "\
        "sports and reading"
print (sencence)


# 多行语句 用 """ 
multiLine = """
使用三引号(\'\'\' 或 \"\"\")
可以指定一个多行字符串。
"""
print(multiLine)


# 用 [] 表示
words=["Today ","is ","Monday "]
print(words)

# 数字有四种类型：整数、布尔型、浮点数和复数。 python是动态类型语言，在运行时会自动判断变量类型，因此无需声明变量类型。
age = 18
height = 1.75
is_male = True

# 使用r禁止转义符
line = "this is a line with \n"
print(line)
lineWithR = r"this is a line with \n"
print(lineWithR)

str1 = "welcome"
print(str1[0:3])
print(str1[3:])
print(str1[:3])
print(str1[0])
print(str1[0::2])
print(str1*2)
print(str1 + "你好！")

# input("\n\n按下 enter 键后退出。")
import sys; x = 'runoob'; sys.stdout.write(x + '\n')
# print不换行
print(str1 + "你好！",end="")
print(str1 + "你好！")


for i in sys.argv: 
    print (i)
print("\n python 路径为：",sys.path)

print("\n ######## 数字类型 ########")
a, b, c, d = 20, 5.5, True, 4+3j
print(type(a),type(b),type(c),type(d))

print(isinstance(a,int))

# Python3 中，bool 是 int 的子类，True 和 False 可以和数字相加， True==1、False==0 会返回 True，但可以通过 is 来判断类型。
print(isinstance(c,int))
issubclass(bool, int) 

print(True==1)
print(True==2)
print(True+1)

print(1 is True)
print(True is 1)
print(1 is int)

# **表示乘方
print(2**3)

#一个变量可以通过赋值指向不同类型的对象。
xx=1
xx="abc"
print(xx)

# 除法，得到一个浮点数
print(2/4)
# 除法，得到一个整数
print(2//4)
# 取余
print(17%3)

# Python 还支持复数，复数由实数部分和虚数部分构成，可以用 a + bj，或者 complex(a,b) 表示， 复数的实部 a 和虚部 b 都是浮点型。
print(4+3j)

word = 'Python'
print(word[0])
# Python 字符串不能被改变。向一个索引位置赋值，比如 word[0] = 'm' 会导致错误。


print("\n")
print(int(2))
print(int(True))


print("\n ######## 布尔类型 ########")
# 使用 bool() 函数进行转换
print(bool(0))
print(bool(20))
print(bool(""))
print(bool(" "))
print(bool([]))
print(bool([1,2]))
print(bool(None))

# 布尔逻辑运算
print(True and False)  # False
print(True or False)   # True
print(not True)        # False

print("\n")
# 布尔值在控制流中的应用
if True:
    print("This will always print")
if not False:
    print("This will also always print")
x = 10
if x:
    print("x is non-zero and thus True in a boolean context")

print("\n ######## 列表 ########")
'''
List（列表） 是 Python 中使用最频繁的数据类型。
列表可以完成大多数集合类的数据结构实现。列表中元素的类型可以不相同，它支持数字，字符串甚至可以包含列表（所谓嵌套）。
列表是写在方括号 [] 之间、用逗号分隔开的元素列表。
'''

list1 = [ 'abcd', 786 , 2.23, 'runoob', 70.2 ]  # 定义一个列表
tinylist = [123, 'runoob']

print (list1)            # 打印整个列表
print (list1[0])         # 打印列表的第一个元素
print (list1[1:3])       # 打印列表第二到第四个元素（不包含第四个元素）
print (list1[2:])        # 打印列表从第三个元素开始到末尾
print (tinylist * 2)    # 打印tinylist列表两次
print (list1 + tinylist)  # 打印两个列表拼接在一起的结果    


print("\n")
input = "I am from Shaoxin City"
input = input.split(" ")
print(input[-1::-2])
print(input[0::2])
print(" ".join(input))

#元组（tuple）与列表类似，不同之处在于元组的元素不能修改。元组写在小括号 () 里，元素之间用逗号隔开。
print("\n ######## 元组 ########")
tuple2 = ("I","am",20,"years","old")
print(tuple2)
# 元组的元素不能修改, 报错：tuple[0]=22

print(type((20))) # 不加逗号表示数学运算中的括号，结果为数字
print(type((20,))) # 元组中只有一个元素时，必须加逗号

print("\n ######## Set集合 ########")
# 集合使用大括号 {} 表示，元素之间用逗号 , 分隔。也可以使用 set() 函数创建集合。创建一个空集合必须用 set() 而不是 { }，因为 { } 是用来创建一个空字典。
set1 = {1,2,3,4,5,"one","two","three"}
print(set1)
set2 = set("2342344325")  # 实际为：{"2","4","3","5"}
set2.add(11)
print(set2)
emptySet = set()
print(emptySet)

print(set([1, 2, 3, 4]))
print(set((1, 2, 3, 4)))
print(set("hello"))

sites = {'Google', 'Taobao', 'Runoob', 'Facebook', 'Zhihu', 'Baidu','Baidu'}
print(sites)   # 输出集合，重复的元素被自动去掉
if('Runoob' in sites):
    print('Runoob 在集合中')

if 'douyin' in sites:
    print('douyin 在集合中')
else:
    print('douyin 不在集合中')

# set可以进行集合运算
a = set('abracadabra') # 去重后实际为{'a', 'r', 'b', 'c', 'd'}
b = set('alacazam')    # 去重后实际为{'a', 'c', 'l', 'z', 'm'}
print(a)
print(a - b)     # a 和 b 的差集
print(a | b)     # a 和 b 的并集
print(a & b)     # a 和 b 的交集
print(a ^ b)     # a 和 b 中不同时存在的元素

print("\n ######## Dictionary字典 ########")
dict1 = {}
dict1['one'] = "1 - 菜鸟教程"
dict1[2]     = "2 - 菜鸟工具"
print(dict1['one'])
if dict1.__contains__("one2"):
    print("one2 在字典中")
else:
    print("one2 不在字典中")

print(dict1[2])
tinydict = {'name': 'runoob','code':1, 'site': 'www.runoob.com'}
print (tinydict)          # 输出完整的字典
print (tinydict.keys())   # 输出所有键
print (tinydict.values()) # 输出所有值

dict2 = dict([('Runoob', 1), ('Google', 2), ('Taobao', 3)])
print(dict2)
print({x: x**2 for x in (2, 4, 6)})

dict3 = dict(Runoob=1, Google=2, Taobao=3)
print(dict3)

print("\n ######## bytes类型 ########")
#在 Python3 中，bytes 类型表示的是不可变的二进制序列（byte sequence）。
#创建 bytes 对象的方式有多种，最常见的方式是使用 b 前缀：
#此外，也可以使用 bytes() 函数将其他类型的对象转换为 bytes 类型。bytes() 函数的第一个参数是要转换的对象，第二个参数是编码方式，如果省略第二个参数，则默认使用 UTF-8 编码：
x = bytes("hello", encoding="utf-8")
print(x)

y=b"hello"
print(y[0:3])
print(x+y)
#与字符串类型不同的是，bytes 类型中的元素是整数值（0 到 255 之间的整数），而不是 Unicode 字符
if b"hello"[0] == ord("h"):
    print("hello[0] == h")
print("\n ######## Python数据类型转换 ########")
# 数据类型的转换，你只需要将数据类型作为函数名即可
print(int(1.23))
print(float(1))
print(str(2))
print(bool(1))
print(eval("1+2+3"))
print(chr(65))
print(ord("A"))
print(hex(255))
print(oct(255))
print(chr(ord("A")))


print("\n ######## 数据类型转换 ########")
#Python 数据类型转换可以分为两种：1. 隐式类型转换 - 自动完成  2.显式类型转换 - 需要使用类型函数来转换
# 我们对两种不同类型的数据进行运算，较低数据类型（整数）就会转换为较高数据类型（浮点数）以避免数据丢失。
num_int = 123
num_flo = 1.23
num_new = num_int + num_flo
print("num_new 数据类型为:",type(num_new))

#print(num_int+"333") 报错：TypeError: unsupported operand type(s) for +: 'int' and 'str'

print("\n ######## 运算符 ########")
# 在 Python 3.8 及更高版本中，引入了一种新的语法特性，称为"海象运算符"（Walrus Operator），它使用 := 符号。这个运算符的主要目的是在表达式中同时进行赋值和返回赋值的值。``
a="abcdssdsdfdfdfdfdfdffdf"
if (n := len(a)) > 10:
    print(f"List is too long ({n} elements, expected <= 10)")

print(0 and 20) #布尔"与" - 如果 x 为 False，x and y 返回 x 的值，否则返回 y 的计算值。
print(1 and 20)
print(0 or 20) #布尔"或" - 如果 x 是 True，它返回 x 的值，否则它返回 y 的计算值。
print(1 or 20)
print(not 0) #布尔"非" - 如果 x 为 True，返回 False 。如果 x 为 False，它返回 True。

if 30:
    print("30 is true")

# Python成员运算符
if 20 in [10,20,30]:
    print("20 is in list")
if 30 in (10,20,30):
    print("30 is in tuple")
if "3" in "123456":
    print("3 is in string")
if "3" in {"1":"a","2":"b","3":"c"}:
    print("3 is in dict")
if 5 in range(1,10): # range(1,10) 创建一个迭代器，迭代器返回的是一个列表，列表中的元素是1到9
    print("5 is in range(1,10)")
if "2" in {"2","3","4"}:
    print("2 is in set")
if "20" not in {"2","3","4"}:
    print("20 is in set") 

print("\n ######## Python身份运算符 ########")
# is 是判断两个标识符是不是引用自一个对象; x is y, 类似 id(x) == id(y) , 如果引用的是同一个对象则返回 True，否则返回 False
print(3 is 3)
print("333" is "333")
print(3 is not 3)
print(id(3) == id(3))

print([1,2,3] is [1,2,3])
print([1,2,3] == [1,2,3])

print("\n ######## Python数字 ########")
# // 得到的并不一定是整数类型的数，它与分母分子的数据类型有关系。
print(7.0//2)
print(7//2)
# 使用 ** 操作来进行幂运算：
print(5 ** 2)
# 在交互模式中，最后被输出的表达式结果被赋值给变量 _ 。 _ 变量应被用户视为只读变量。

print(abs(-100))
print(math.ceil(3.14))
print(math.floor(3.14))
print(round(3.14))
print(round(3.1415926, 2))
print(max(1, 2, 3, 4, 5))
print(min(1, 2, 3, 4, 5))
print(sum([1, 2, 3, 4, 5]))
print(math.exp(1))
print(math.pow(2, 3))
print(math.sqrt(9)) 

import random
# 随机函数
print(random.choice(range(10)))
print(random.randrange(1,10,2))
print(random.random())
print(random.randint(10,20))
shuffleList = [1,2,3,4,5]
random.shuffle(shuffleList)
print(shuffleList)
print(random.uniform(30,40))

print("\n ######## Python 转义字符 ########")

#回车，将 \r 后面的内容移到字符串开头，并逐一替换开头部分的字符，直至将 \r 后面的内容完全替换完成。
print("Hello\rWorld!")
print('google runoob taobao\r123456')

print("\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21")

import time
for i in range(101):
    print("\r{:3}%".format(i), end="")
    time.sleep(0.0005)

print ("\n我叫 %s 今年 %d 岁!" % ('小明', 10))

# f-string
# f-string 是 python3.6 之后版本添加的，称之为字面量格式化字符串，是新的格式化字符串的语法。f-string 格式化字符串以 f 开头，后面跟着字符串，字符串中的表达式用大括号 {} 包起来，它会将变量或表达式计算后的值替换进去
print('Hello %s' % "kim")
print(f"hello {'kim'}")
print(f"1+1= {1+1}")
# 在 Python 3.8 的版本中可以使用 = 符号来拼接运算表达式与结果：
print(f"{1+2=}")

print("\n ######## Python 的字符串内建函数 ########")
print("hello world".capitalize(),"hello".center(20,"*"),"hello".count("l"),)
bb = "hello".encode("utf-8")
print(bb)
print(bb.decode("utf-8"))
print("hello".endswith("o"))
print("wellcome to china".find("to"))

#检查字符串是否由字母和数字组成，即字符串中的所有字符都是字母或数字。如果字符串至少有一个字符，并且所有字符都是字母或数字，则返回 True；否则返回 False。
print("@".isalnum(),"123".isdigit(),"abcB".islower(),)

# join() 方法用于将序列中的元素以指定的字符连接生成一个新的字符串。
print("-".join(["a","b","c"]))

print("hello".ljust(10,"*"),"hello".rjust(10,"*"))
print("hello    ".lstrip(),"****hello".lstrip("*"))
print(max("abcdefg"))
print("hello".replace("l","i",1))
print("hello".rfind("l"))
print("hello kim, where are you from".split(" "))
print("***hello***".strip("*"))
print("Hello".swapcase())

print("\n ######## Python 列表 ########")
lists = ['Google', 'Runoob', 1997, 2000]
lists.append("Baidu")
print(lists)
del lists[2]
print(lists)
print(len([1,2,3]),[1,2,3]+[4,5,6],["Hi "]*3,3 in [1,2,3])

# 列表比较
import operator
a = [1, 2]
b = [2, 3]
c = [2, 3]
print("operator.eq(a,b): ", operator.eq(a,b))
print("operator.eq(c,b): ", operator.eq(c,b))


print(list(range(10)))
print(list((123, 'Google', 'Runoob', 'Taobao')))

print("\n ######## Python 元组 ########")
# 元组中的元素值是不允许修改的; 所谓元组的不可变指的是元组所指向的内存中的内容不可变。
tup3 = "a", "b", "c", "d"   #  不需要括号也可以
print(tup3,type(tup3))
# 元组中只包含一个元素时，需要在元素后面添加逗号 , ，否则括号会被当作运算符使用：
print((50,)) 

print("\n ######## Python 字典 ########")
tinydict2 = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}
del tinydict2['Name']
print(tinydict2)
print(str(tinydict2))

dictCopy = tinydict2.copy()
print(dictCopy)

tinydict2.clear()
print(tinydict2)
dictCopy["Address"] = "Zhejiang"

print(dict.fromkeys(("1","2","3")))
print(dictCopy.get("Name","Kim"))
print("Name" in dictCopy)
print(dictCopy.items())
print(dictCopy.keys())

dictCopy.update({"Name":"Tom","Age":18})
print(dictCopy)
print(dictCopy.values())
print(dictCopy.pop("Age"))
print(dictCopy)
print(dictCopy.popitem())
print(dictCopy)

print("\n ######## Python 集合 ########")
set1 = {"Apple","Banana","Orange"}
set1.update([1,2,3])
set1.update({4,5})
set1.add("hello")
print(set1)
set1.remove("hello")
set1.discard(4)
print(set1)

set1.pop()
print(set1)

print("\n ######## Python 条件控制 ########")

c=0
while c<10:
    if c%2==0:
        print(c,"is even")
    elif c%2==1:
        print(c,"is odd")
    c+=1

# match...case 的条件判断; match 后的对象会依次与 case 后的内容进行匹配，如果匹配成功，则执行匹配到的表达式，否则直接跳过，_ 可以匹配一切。
type="apple2"
match type:
    case "apple" | "banana":
        print("apple")

    case _:
        print("unknown")
    
# 如果 while 后面的条件语句为 false 时，则执行 else 的语句块。
count = 0
while count < 5:
   print (count, " 小于 5")
   count = count + 1
else:
   print (count, " 大于或等于 5")

# Python for 循环可以遍历任何可迭代对象，如一个列表或者一个字符串。
# for...else 语句用于在循环结束后执行一段代码。
# 当循环执行完毕（即遍历完 iterable 中的所有元素）后，会执行 else 子句中的代码，如果在循环过程中遇到了 break 语句，则会中断循环，此时不会执行 else 子句。
for i in [1, 2, 3, 4]:
    print(i)
    if i == 3:
        print(" i == 3 break")
        break
else:
    print("for 循环结束")

# Python pass是空语句，是为了保持程序结构的完整性。pass 不做任何事情，一般用做占位语句.

 
# Fibonacci series: 斐波纳契数列
# 两个元素的总和确定了下一个数
a, b = 0, 1
while b < 100000:
    print(b, end=',')
    a, b = b, a+b

print("\n ######## Python 推导式 ########")
"""
Python 推导式是一种独特的数据处理方式，可以从一个数据序列构建另一个新的数据序列的结构体。
Python 推导式是一种强大且简洁的语法，适用于生成列表、字典、集合和生成器。
在使用推导式时，需要注意可读性，尽量保持表达式简洁，以免影响代码的可读性和可维护性。
Python 支持各种数据结构的推导式：
	列表(list)推导式  [表达式 for 变量 in 列表 if 条件]
	字典(dict)推导式  { key_expr: value_expr for value in collection if condition }
	集合(set)推导式
	元组(tuple)推导式
"""
# 列表推导式
num = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print([n*2 for n in num if n % 2 == 0])

words = ["hi","apple","welcome"]
print({key:len(key) for key in words if len(key)>=5})

fruits = {"apple":1,"banana":2}
print(fruits)
fruitCountSet = {fruits[fruit] for fruit in fruits}
print(fruitCountSet)
fruits = {name:fruits[name]+1 for name in fruits}
print(fruits)

# 字典推导式
nums = [1, 1, 1, 2, 3, 3, 6, 6,]
numMap = {num:nums.count(num) for num in nums}
print(numMap)

# 集合推导式
a = {x for x in 'abracadabra' if x not in 'abc'}
print(a)

# 元组推导式  元组推导式返回的结果是一个生成器对象。
a = (x for x in range(1,10)) 
print(a)   
print(tuple(a)) # 使用 tuple() 函数，可以直接将生成器对象转换成元组

print("\n ######## Python 迭代器与生成器 ########")
# 迭代器对象从集合的第一个元素开始访问，直到所有的元素被访问完结束。迭代器只能往前不会后退。
# 迭代器有两个基本的方法：iter() 和 next()。 字符串，列表或元组对象都可用于创建迭代器：

list3 = [1,2,3,4,5,6]
it = iter(list3)
print(next(it))
print(next(it))
for x in it:
    print (x, end=" ")
    if x == 4:
        break
flag=True
while flag:
    try:
        print(next(it))
    except StopIteration:
        print("StopIteration")
        flag=False
        #sys.exit()

class MyNumber:
    def __iter__(self):
        self.a=1
        return self
    def __next__(self):
        if self.a<=3:
            x=self.a
            self.a+=1
            return x
        else:
            raise StopAsyncIteration
myNum = MyNumber()
myIter = iter(myNum)
try:
    for x in myIter:
        print(x)
except StopAsyncIteration:
    print("StopAsyncIteration")

# 生成器 在 Python 中，使用了 yield 的函数被称为生成器（generator）。yield 是一个关键字，用于定义生成器函数，生成器函数是一种特殊的函数，可以在迭代过程中逐步产生值，而不是一次性返回所有结果。
# 生成器函数的优势是它们可以按需生成值，避免一次性生成大量数据并占用大量内存
def countDown(n):
    while n>0:
        yield n 
        n-=1
       
# 创建生成器对象
generator = countDown(3)
print(next(generator))
for i in generator:
    print(i)
